use std::collections::HashMap;
use std::ops::Add;
use std::fmt::Formatter;
use std::borrow::Borrow;
use protobuf::Message;
use crate::key_value_serialize::{SerializeValueType, SerializeInt32, SerializeInt64, SerializeDouble, SerializeFloat, SerializeString, SerializeBool};
use std::fs::{File, OpenOptions};
use std::io::{Write, ErrorKind, Read}; 

// 序列化模块
mod key_value_serialize;

// 类型定义
pub enum ValueType {
    UNDEFINE,
    BOOL,
    INT8,
    INT32,
    INT64,
    FLOAT,
    DOUBLE,
    STRING,
    // 其他类型
}

impl std::fmt::Display for ValueType {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            ValueType::BOOL => write!(f, "BOOL"),
            ValueType::INT8 => write!(f, "INT8"),
            ValueType::INT32 => write!(f, "INT32"),
            ValueType::INT64 => write!(f, "INT64"),
            ValueType::FLOAT => write!(f, "FLOAT"),
            ValueType::DOUBLE => write!(f, "DOUBLE"),
            ValueType::STRING => write!(f, "STRING"),
            _ => write!(f, "UNDEFINE")
        }
    }
}

pub trait KeyValueTool<T> {
    /*
    插入操作
     */
    fn set(&mut self, key: &str, value: T);
}

// 总表
pub struct KeyValueDataMap {
    m_project_name: String,
    m_int8_map: HashMap<String, i8>,
    m_int32_map: HashMap<String, i32>,
    m_int64_map: HashMap<String, i64>,
    m_float_map: HashMap<String, f32>,
    m_double_map: HashMap<String, f64>,
    m_bool_map: HashMap<String, bool>,
    m_str_map: HashMap<String, String>,
    m_bridge_map: HashMap<String, ValueType>,

}

// 继承
impl KeyValueTool<i8> for KeyValueDataMap {
    fn set(&mut self, key: &str, value: i8) {
        self.m_int8_map.insert(String::from(key), value);
        self.m_bridge_map.insert(String::from(key), ValueType::INT8);
    }
}

impl KeyValueTool<i32> for KeyValueDataMap {
    fn set(&mut self, key: &str, value: i32) {
        self.m_int32_map.insert(String::from(key), value);
        self.m_bridge_map.insert(String::from(key), ValueType::INT32);
    }
}

impl KeyValueTool<bool> for KeyValueDataMap {
    fn set(&mut self, key: &str, value: bool) {
        self.m_bool_map.insert(String::from(key), value);
        self.m_bridge_map.insert(String::from(key), ValueType::BOOL);
    }
}

impl KeyValueTool<i64> for KeyValueDataMap {
    fn set(&mut self, key: &str, value: i64) {
        self.m_int64_map.insert(String::from(key), value);
        self.m_bridge_map.insert(String::from(key), ValueType::INT64);
    }
}

impl KeyValueTool<f32> for KeyValueDataMap {
    fn set(&mut self, key: &str, value: f32) {
        self.m_float_map.insert(String::from(key), value);
        self.m_bridge_map.insert(String::from(key), ValueType::FLOAT);
    }
}

impl KeyValueTool<f64> for KeyValueDataMap {
    fn set(&mut self, key: &str, value: f64) {
        self.m_double_map.insert(String::from(key), value);
        self.m_bridge_map.insert(String::from(key), ValueType::DOUBLE);
    }
}

impl KeyValueTool<String> for KeyValueDataMap {
    fn set(&mut self, key: &str, value: String) {
        self.m_str_map.insert(String::from(key), value);
        self.m_bridge_map.insert(String::from(key), ValueType::STRING);
    }
}

impl KeyValueTool<&str> for KeyValueDataMap {
    fn set(&mut self, key: &str, value: &str) {
        self.m_str_map.insert(String::from(key), String::from(value));
        self.m_bridge_map.insert(String::from(key), ValueType::STRING);
    }
}

impl KeyValueDataMap
{
    pub fn get_project_name(&self) -> &String
    {
        self.m_project_name.borrow()
    }
    pub fn get_type(&self, key: &str) -> Option<&ValueType> {
        let t = self.m_bridge_map.get(key);
        t
    }

    pub fn get_bool(&self, key: &str) -> Option<&bool> {
        let v = self.m_bool_map.get(key);
        v
    }

    pub fn get_int8(&self, key: &str) -> Option<&i8> {
        let v = self.m_int8_map.get(key);
        v
    }

    pub fn get_int32(&self, key: &str) -> Option<&i32> {
        let v = self.m_int32_map.get(key);
        v
    }

    pub fn get_int64(&self, key: &str) -> Option<&i64> {
        let v = self.m_int64_map.get(key);
        v
    }
    pub fn get_float(&self, key: &str) -> Option<&f32> {
        let v = self.m_float_map.get(key);
        v
    }
    pub fn get_double(&self, key: &str) -> Option<&f64> {
        let v = self.m_double_map.get(key);
        v
    }
    pub fn get_string(&self, key: &str) -> Option<&String> {
        let v = self.m_str_map.get(key);
        v
    }

    pub fn get_value(&self, key: &str, show: bool) -> String {
        let null_str = String::from("(null)");
        let v = self.get_type(key);

        let v = match v.unwrap_or(&ValueType::UNDEFINE) {
            ValueType::UNDEFINE => {
                null_str
            },
            ValueType::BOOL => {
                let isok = self.m_bool_map.get(key);

                let hander = if show {
                    "(Bool) "
                } else {
                    ""
                };
                if *isok.unwrap() == true {
                    String::from(hander).add("True")
                } else {
                    String::from(hander).add("False")
                }
            },
            ValueType::INT8 => {
                let str = self.m_int8_map.get(key).unwrap().to_string();
                if show
                {
                    String::from("(INT8) ").add(str.as_str())
                } else {
                    str
                }
            },
            ValueType::INT32 => {
                let str = self.m_int32_map.get(key).unwrap().to_string();

                if show
                {
                    String::from("(INT32) ").add(str.as_str())
                } else {
                    str
                }
            },
            ValueType::INT64 => {
                let str = self.m_int64_map.get(key).unwrap().to_string();
                if show
                {
                    String::from("(INT64) ").add(str.as_str())
                } else {
                    str
                }
            },
            ValueType::FLOAT => {
                let str = self.m_float_map.get(key).unwrap().to_string();
                if show
                {
                    String::from("(FLOAT) ").add(str.as_str())
                } else {
                    str
                }
            },
            ValueType::DOUBLE => {
                let str = self.m_double_map.get(key).unwrap().to_string();
                if show
                {
                    String::from("(DOUBLE) ").add(str.as_str())
                } else {
                    str
                }
            },
            ValueType::STRING => {
                let str = self.m_str_map.get(key).unwrap().to_string();
                if show
                {
                    String::from("(STRING) ").add(str.as_str())
                } else {
                    str
                }
            }
        };
        v
    }

    pub fn for_echo(&self, cb: fn(key: &str, v_type: &ValueType, value: &String), show: bool) {
        for (key, vt) in self.m_bridge_map.iter() {
            cb(key.as_str(), vt, &self.get_value(key, show));
        }
    }
}


pub fn new(name: &str) -> KeyValueDataMap
{
    KeyValueDataMap {
        m_project_name: String::from(name),
        m_int8_map: HashMap::default(),
        m_int32_map: HashMap::default(),
        m_int64_map: HashMap::default(),
        m_float_map: Default::default(),
        m_double_map: Default::default(),
        m_bool_map: Default::default(),
        m_str_map: Default::default(),
        m_bridge_map: Default::default(),
    }
}


pub trait FilePersistenceImpl
{
    fn set_file_name(&mut self, filename: &str);

    fn save(&self);

    fn load(&mut self);
}

impl FilePersistenceImpl for KeyValueDataMap
{
    fn set_file_name(&mut self, filename: &str) {
        self.m_project_name = String::from(filename);
    }

    fn save(&self) {
        // 序列化所有
        let mut cache_list = key_value_serialize::SerialStringList::new();
        let mut temp_map: HashMap<String, key_value_serialize::SerialByteDataType> = HashMap::new();
        for (key, v_type) in self.m_bridge_map.iter() {
            match v_type {
                ValueType::BOOL => {
                    let value_data = self.m_bool_map.get(key);
                    let mut data = key_value_serialize::SerializeBool::new();
                    data.set_data(*value_data.unwrap() );

                    let data = data.write_to_bytes().expect("error");
                    let mut serial = key_value_serialize::SerialByteDataType::new();
                    serial.value_type = key_value_serialize::SerializeValueType::Bool_TYPE;
                    serial.set_data(data);
                    temp_map.insert(String::from(key), serial);
                }

                ValueType::INT8 => {
                    let value_data = self.m_int8_map.get(key);
                    let mut data = key_value_serialize::SerializeInt32::new();
                    data.set_data(*value_data.unwrap() as i32);

                    let data = data.write_to_bytes().expect("error");
                    let mut serial = key_value_serialize::SerialByteDataType::new();
                    serial.value_type = key_value_serialize::SerializeValueType::INT32_TYPE;
                    serial.set_data(data);
                    temp_map.insert(String::from(key), serial);
                }
                ValueType::INT32 => {
                    let value_data = self.m_int32_map.get(key);
                    let mut data = key_value_serialize::SerializeInt32::new();
                    data.set_data(*value_data.unwrap());

                    let data = data.write_to_bytes().expect("error");
                    let mut serial = key_value_serialize::SerialByteDataType::new();
                    serial.value_type = key_value_serialize::SerializeValueType::INT32_TYPE;
                    serial.set_data(data);
                    temp_map.insert(String::from(key), serial);
                }
                ValueType::INT64 => {
                     let value_data = self.m_int64_map.get(key);
                    let mut data = key_value_serialize::SerializeInt64::new();
                    data.set_data(*value_data.unwrap());

                    let data = data.write_to_bytes().expect("error");
                    let mut serial = key_value_serialize::SerialByteDataType::new();
                    serial.value_type = key_value_serialize::SerializeValueType::INT64_TYPE;
                    serial.set_data(data);
                    temp_map.insert(String::from(key), serial);
                }

                ValueType::FLOAT => {
                    let value_data = self.m_float_map.get(key);
                    let mut data = key_value_serialize::SerializeFloat::new();
                    data.set_data(*value_data.unwrap());

                    let data = data.write_to_bytes().expect("error");
                    let mut serial = key_value_serialize::SerialByteDataType::new();
                    serial.value_type = key_value_serialize::SerializeValueType::Float_TYPE;
                    serial.set_data(data);
                    temp_map.insert(String::from(key), serial);                }

                ValueType::DOUBLE => {
                    let value_data = self.m_double_map.get(key);
                    let mut data = key_value_serialize::SerializeDouble::new();
                    data.set_data(*value_data.unwrap());

                    let data = data.write_to_bytes().expect("error");
                    let mut serial = key_value_serialize::SerialByteDataType::new();
                    serial.value_type = key_value_serialize::SerializeValueType::Double_TYPE;
                    serial.set_data(data);
                    temp_map.insert(String::from(key), serial);
                }
                ValueType::STRING => {
                    let value_data = self.m_str_map.get(key);
                    let mut data = key_value_serialize::SerializeString::new();
                    let stringdata  = value_data.unwrap();
                    data.set_data(stringdata.to_owned().into_bytes());
                    //
                    let data = data.write_to_bytes().expect("error");
                    let mut serial = key_value_serialize::SerialByteDataType::new();
                    serial.value_type = key_value_serialize::SerializeValueType::String_TYPE;
                    serial.set_data(data);
                    temp_map.insert(String::from(key), serial);
                }
                _ => {
                    println!("pass");
                }
            }
        }
        // 写入文件
        cache_list.set_datas(temp_map);
        let buff = cache_list.write_to_bytes().unwrap();
        let f = OpenOptions::new().write(true).open( self.m_project_name.as_str());
        let mut f = match f {
            Ok(file) => file,
            Err(error) => match error.kind() {
                ErrorKind::NotFound => match File::create( self.m_project_name.as_str()) {
                    Ok(fc) => fc,
                    Err(e) => panic!("Problem creating the file: {:?}", e),
                },
                other_error => panic!("Problem opening the file: {:?}", other_error),
            },
        };

        f.write_all(buff.as_slice()).unwrap();
        // println!("write : {:?} " , buff.as_slice());

    }

    fn load(&mut self) {
        // let buff = cache_list.write_to_bytes().unwrap();
        let f = OpenOptions::new().read(true).open( self.m_project_name.as_str());
        let mut f = match f {
            Ok(file) => file,
            Err(error) => match error.kind() {
                ErrorKind::NotFound => match File::create( self.m_project_name.as_str()) {
                    Ok(fc) => fc,
                    Err(e) => panic!("Problem creating the file: {:?}", e),
                },
                other_error => panic!("Problem opening the file: {:?}", other_error),
            },
        };

        // let buff =   fs::read_to_string(self.m_project_name.as_str()).unwrap();
        let mut  buff= Vec::new();
        f.read_to_end(&mut buff).unwrap_or(0);
        // println!("ok {:?}" ,buff );

        // 反序列化
        let mut cache_list =key_value_serialize::SerialStringList::new();
        cache_list.merge_from_bytes(&buff).unwrap();

        let data = cache_list.datas;
        for (key , serial_type) in data.iter() {
            match serial_type.value_type {
                SerializeValueType::Bool_TYPE => {
                    // 反序列化
                    let mut data_value = SerializeBool::new();
                    data_value.merge_from_bytes(serial_type.get_data()).unwrap_or(Vec::new().insert(0 , 0));
                    self.m_bool_map.insert(key.to_string(), data_value.data);
                    self.m_bridge_map.insert(key.to_string() , ValueType::BOOL);
                }
                SerializeValueType::INT32_TYPE => {
                    // 反序列化
                    let mut int32data = SerializeInt32::new();
                    int32data.merge_from_bytes(serial_type.get_data()).unwrap_or(Vec::new().insert(0 , 0));
                    self.m_int32_map.insert(key.to_string() , int32data.data);
                    self.m_bridge_map.insert(key.to_string() , ValueType::INT32);
                }
                SerializeValueType::INT64_TYPE => {
                    // 反序列化
                    let mut int64data = SerializeInt64::new();
                    int64data.merge_from_bytes(serial_type.get_data()).unwrap_or(Vec::new().insert(0 , 0));
                    self.m_int64_map.insert(key.to_string() , int64data.data);
                    self.m_bridge_map.insert(key.to_string() , ValueType::INT64);
                }
                SerializeValueType::Float_TYPE => {
                    // 反序列化
                    let mut data_value = SerializeFloat::new();
                    data_value.merge_from_bytes(serial_type.get_data()).unwrap_or(Vec::new().insert(0 , 0));
                    self.m_float_map.insert(key.to_string(), data_value.data);
                    self.m_bridge_map.insert(key.to_string() , ValueType::FLOAT);

                }
                SerializeValueType::Double_TYPE => {
                    // 反序列化
                    let mut data_value = SerializeDouble::new();
                    data_value.merge_from_bytes(serial_type.get_data()).unwrap_or(Vec::new().insert(0 , 0));
                    self.m_double_map.insert(key.to_string(), data_value.data);
                    self.m_bridge_map.insert(key.to_string() , ValueType::DOUBLE);

                }
                SerializeValueType::String_TYPE => {
                    // 反序列化
                    let mut data_value = SerializeString::new();
                    data_value.merge_from_bytes(serial_type.get_data()).unwrap_or(Vec::new().insert(0 , 0));
                    let strdata  = String::from_utf8(data_value.get_data().to_vec()).unwrap_or(String::from(""));
                    self.m_str_map.insert(key.to_string(),strdata);
                    self.m_bridge_map.insert(key.to_string() , ValueType::STRING);
                }
                _ => {
                    println!("pass");
                }
            }
        }
    }
}


#[cfg(test)]
mod tests {
    use std::fs::File;
    use std::path::Path;
    use std::io::{ErrorKind, Write};

    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }

}
